
#include "stdafx.h"
#include "SmallMediaPlayer.h"

namespace SmallMediaLibrary{

	MediaPlayer::MediaPlayer()
	{
		mGraphBuilder = 0;
		mMediaControl = 0;
		mMediaSeeking = 0;
	}

	void MediaPlayer::Initialise()
	{
		Shutdown();

		IGraphBuilder* pGraphBuilder;
		IMediaControl* pMediaControl;
		IMediaSeeking* pMediaSeeking;

		HRESULT hr = CoCreateInstance(	CLSID_FilterGraph,
										NULL,
										CLSCTX_INPROC_SERVER,
										IID_IGraphBuilder,
										(void**)(&pGraphBuilder) );

		if(!SUCCEEDED(hr))
		{
			String^ message = String::Format("Unable to create IGraphBuilder {0}", hr);
			throw gcnew System::Exception(message);
		}		
		mGraphBuilder = pGraphBuilder;

		hr = mGraphBuilder->QueryInterface(IID_IMediaControl,
                                   (void **)&pMediaControl);

		if(!SUCCEEDED(hr))
		{
			String^ message = String::Format("Unable to create IMediaControl {0}", hr);
			throw gcnew System::Exception(message);
		}
		mMediaControl = pMediaControl;

		hr = mGraphBuilder->QueryInterface(IID_IMediaSeeking,
                                   (void**)&pMediaSeeking);

		if(!SUCCEEDED(hr))
		{
			String^ message = String::Format("Unable to create IMediaSeeking {0}", hr);
			throw gcnew System::Exception(message);
		}
		mMediaSeeking = pMediaSeeking;
	}


	HRESULT MediaPlayer::CheckFilterGraphFor(IFilterGraph *pGraph, IBaseFilter* pFilterToLookFor)
	{
		IEnumFilters *pEnum = NULL;
		IBaseFilter *pFilter;
		ULONG cFetched;

		HRESULT enumeratedFilterCount = 0;

		FILTER_INFO pRefFilterInfo;
		pFilterToLookFor->QueryFilterInfo(&pRefFilterInfo);

		HRESULT hr = pGraph->EnumFilters(&pEnum);
		if (SUCCEEDED(hr))
		{
			while(pEnum->Next(1, &pFilter, &cFetched) == S_OK)
			{
				enumeratedFilterCount--;

				FILTER_INFO FilterInfo;
				hr = pFilter->QueryFilterInfo(&FilterInfo);
				if (SUCCEEDED(hr))
				{	
					if(wcscmp(FilterInfo.achName, pRefFilterInfo.achName) == 0)
					{
						pRefFilterInfo.pGraph->Release();
						return S_OK;	
					}

					// The FILTER_INFO structure holds a pointer to the Filter Graph
					// Manager, with a reference count that must be released.
					if (FilterInfo.pGraph != NULL)
					{
						FilterInfo.pGraph->Release();
					}
					pFilter->Release();

				}
			}

			pEnum->Release();
		}

		pRefFilterInfo.pGraph->Release();
		return enumeratedFilterCount;
	}

	void MediaPlayer::Shutdown()
	{
		if(mMediaControl > 0)
		{
			mMediaControl->Stop();
			mMediaControl->Release();
		}

		if(mMediaSeeking > 0)
		{
			mMediaSeeking->Release();
		}

		if(mGraphBuilder > 0)
		{
			mGraphBuilder->Release();
		}
	}

	// Loads the provided file and creates a filter graph automatically
	void MediaPlayer::Load(String^ filename)
	{
		Initialise();

		pin_ptr<const wchar_t> wFilename = PtrToStringChars(filename);
		mGraphBuilder->RenderFile(wFilename, NULL);

		REFERENCE_TIME duration;
		mMediaSeeking->GetDuration(&duration);
		mDuration = duration;
	}

	void MediaPlayer::Play()
	{
		mMediaControl->Run();
	}

	void MediaPlayer::Stop()
	{
		mMediaControl->Stop();
	}

	void MediaPlayer::Pause()
	{
		mMediaControl->Pause();
	}

	void MediaPlayer::Seek(long time_ms)
	{
		REFERENCE_TIME t = ((REFERENCE_TIME)time_ms * (REFERENCE_TIME)(1000 * 10));
		mMediaSeeking->SetPositions(&t, AM_SEEKING_AbsolutePositioning, NULL, AM_SEEKING_NoPositioning);
	}

	MediaPlayer::~MediaPlayer()
	{
		Shutdown();
	}


}
